
/*


Config是一个适配器接口，用于解析配置文件以将原始数据获取到Configer，就是将不同的结构数据导入在config存储器中，进行存取操作，支持Ini、yaml、xml、json、env格式。
NewConfig 和 NewConfigData 生成一个Configer,Register提供数据注册到Configer中，在进行一系列操作。


*/ 
// config/config.go 

// NewConfig adapterName is ini/json/xml/yaml.
func NewConfig(adapterName, filename string) (Configer, error) { 
	return adapter.Parse(filename) }

func NewConfigData(adapterName string, data []byte) (Configer, error) {
	 return adapter.ParseData(data) }

func Register(name string, adapter Config) { 
	// code ...
	adapters[name] = adapter
}

// Configer defines how to get and set value from configuration raw data.
type Configer interface {
	Set(key, val string) error  
	String(key string) string   
	Strings(key string) []string 
	Int(key string) (int, error)
	Int64(key string) (int64, error)
	Bool(key string) (bool, error)
	Float(key string) (float64, error)
	DefaultString(key string, defaultVal string) string     
	DefaultStrings(key string, defaultVal []string) []string 
	DefaultInt(key string, defaultVal int) int
	DefaultInt64(key string, defaultVal int64) int64
	DefaultBool(key string, defaultVal bool) bool
	DefaultFloat(key string, defaultVal float64) float64
	DIY(key string) (interface{}, error)
	GetSection(section string) (map[string]string, error)
	SaveConfigFile(filename string) error
}

// Config is the adapter interface for parsing config file to get raw data to Configer.
type Config interface {
	Parse(key string) (Configer, error)
	ParseData(data []byte) (Configer, error)
}

/*
	config/fake.go 定义个私有的map存储器，通过 NewFakeConfig() 得到存储器的使用权，
	以 key-string ：value-string 键值对进行 Set 存入，获取不同类型的value有对应的函数。
*/ 
type fakeConfigContainer struct {
	data map[string]string
}

var _ Configer = new(fakeConfigContainer)

// NewFakeConfig return a fake Configer
func NewFakeConfig() Configer {
	return &fakeConfigContainer{
		data: make(map[string]string),
	}
}


/*
已JSON为例，通过实现config.go文件中的Config接口的Parse,ParseData方法返回其Configer具体实现类。
*/

// JSONConfig is a json config parser and implements Config interface.
type JSONConfig struct {
}
// Parse returns a ConfigContainer with parsed json config map.
func (js *JSONConfig) Parse(filename string) (Configer, error) {
	// code ...
	return js.ParseData(content)
}

// ParseData returns a ConfigContainer with json string
func (js *JSONConfig) ParseData(data []byte) (Configer, error) {
	x := &JSONConfigContainer{
		data: make(map[string]interface{}),
	}
	// code ...
	x.data = ExpandValueEnvForMap(x.data)
	return x, nil
}
